package com.rykj.qxj.server.services.impl;

import com.github.pagehelper.util.StringUtil;
import com.rykj.qxj.server.common.constants.LevelEnum;
import com.rykj.qxj.server.common.exception.ApiAbilityStaticsticsIsNullException;
import com.rykj.qxj.server.common.exception.AppIdIsNullException;
import com.rykj.qxj.server.common.exception.ApplyIsNotExistException;
import com.rykj.qxj.server.dao.ApiAbilityStatisticsMapper;
import com.rykj.qxj.server.dao.ApiManageMapper;
import com.rykj.qxj.server.dao.ApplyManageMapper;
import com.rykj.qxj.server.dao.DataMartMapper;
import com.rykj.qxj.server.model.entity.ApiAbilityStatistics;
import com.rykj.qxj.server.model.entity.ApiManage;
import com.rykj.qxj.server.model.entity.Apply;
import com.rykj.qxj.server.model.entity.DataMart;
import com.rykj.qxj.server.services.IApiAbilityStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class ApiAbilityStatisticsServiceImpl implements IApiAbilityStatisticsService {
	
	@Autowired
	private ApplyManageMapper applyManageMapper;
	
	@Autowired
	private ApiAbilityStatisticsMapper apiAbilityStatisticsMapper;
	
	@Autowired
	private ApiManageMapper apiManageMapper;
	
	@Autowired
	private DataMartMapper dataMartMapper;
	
	private final static int  COUNT_TYPE_BROWSER=5;
	private final static int  COUNT_TYPE_API_VISIT=6;

	@Override
	public void saveApiAbilityStatistics(ApiAbilityStatistics apiAbilityStatistics)
			throws ApplyIsNotExistException, AppIdIsNullException, ApiAbilityStaticsticsIsNullException {
		if(apiAbilityStatistics ==null) {
			throw new ApiAbilityStaticsticsIsNullException("保存信息不能为空");
			
		}
		if(StringUtil.isEmpty(apiAbilityStatistics.getAppKey())) {
			throw new AppIdIsNullException("应用的appKey不能为空");
			
		}
		Apply apply = applyManageMapper.selectApplyByApplyId(apiAbilityStatistics.getAppKey());
		if(apply ==null) {
			throw new ApplyIsNotExistException("此appKey没有对应的应用,请检查");
			
		}
		apiAbilityStatistics.setCreateDate(new Date());
		apiAbilityStatisticsMapper.insert(apiAbilityStatistics);

	}

	/*@Override
	public Map<String,Object> selectApiAbilityStatisticsList(String appKey) {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		//Date addHowDay = DateUtils.addHowDay(new Date(), -1);
		String todayDate = sdf.format(new Date());
		
		Map<String,Object> paramMap=new HashMap<String, Object>();
		paramMap.put("appKey", appKey);
		paramMap.put("curDate", todayDate);
     	List<ApiAbilityStatistics> apiAbilityStatisticsList = apiAbilityStatisticsMapper.selectApiAbilityStatisticsList(paramMap);
    	JSONArray browserArray=new JSONArray();
     	JSONObject  browserObject=new JSONObject();
     	int sum=0;
     	Map<String,Object> resultMap=new HashMap<String,Object>();
     	if(apiAbilityStatisticsList!=null) {
     		for (ApiAbilityStatistics apiAbilityStatistics : apiAbilityStatisticsList) {
     			if(apiAbilityStatistics.getCountType()==COUNT_TYPE_BROWSER) {
     				if(apiAbilityStatistics.getBrowserType().indexOf("MSIE")!=-1) {
     					browserObject.put("IE", apiAbilityStatistics.getCountValue());
     				}else if(apiAbilityStatistics.getBrowserType().indexOf("Edge")!=-1) {
     					browserObject.put("Edge", apiAbilityStatistics.getCountValue());
     					
     				}else if(apiAbilityStatistics.getBrowserType().indexOf("Firefox")!=-1) {
     					browserObject.put("Firefox", apiAbilityStatistics.getCountValue());
     					
     				}else if(apiAbilityStatistics.getBrowserType().indexOf("OPR")!=-1) {
     					browserObject.put("Opera", apiAbilityStatistics.getCountValue());
     					
     				}else if(apiAbilityStatistics.getBrowserType().indexOf("Chrome")!=-1) {
     					browserObject.put("Chrome", apiAbilityStatistics.getCountValue());
     					
     				}else if(apiAbilityStatistics.getBrowserType().indexOf("Safari")!=-1) {
     					browserObject.put("Safari", apiAbilityStatistics.getCountValue());
     				}else {
     					sum+=Integer.valueOf(apiAbilityStatistics.getCountValue());
     					browserObject.put("Other", sum);
     				}
     			}
			}
     		//自定义按照访问量倒序排序
    		Collections.sort(apiVisitList, new Comparator<Map<String,Object>>(){
				@Override
				public int compare(Map<String, Object> o1, Map<String, Object> o2) {
					int temp=Double.valueOf(o1.get("visitCount").toString())>Double.valueOf(o2.get("visitCount").toString())?-1:0;
					return temp;
				}
    			
    		});
    	   List<Map<String, Object>> apiVisitCountListMap = apiAbilityStatisticsMapper.selectApiVisitCountList(paramMap);
    	   if(apiVisitCountListMap!=null) {
    		   for (Map<String, Object> map : apiVisitCountListMap) {
    			   String url = (String) map.get("url");
    			   String fullUrl="";
       			 int indexOf = url.indexOf('?');
       			 if(indexOf!=-1) {
       				fullUrl=url.substring(0, indexOf);
       			 }else {
       				fullUrl=url;
       			 }
       			map.put("url", fullUrl);
       			String pathInDatabase = fullUrl.replace("/weather-api", "");
       			ApiManage apiManage = apiManageMapper.validateApiUrl(pathInDatabase);
       			if(apiManage!=null) {
       				map.put("name", apiManage.getName());
       			}
			}
    	   }
    	   List<Map<String,Object>> countList=new ArrayList<Map<String,Object>>();
    	   for(int i=0;i<apiVisitCountListMap.size();i++) {
    		   Object url = apiVisitCountListMap.get(i).get("url");  
	            int flag = 0;
	            for (int j = 0; j < countList.size(); j++) {  
	                Object url_ = countList.get(j).get("url");  
	                if (url.toString().equals(url_.toString())) {  
	                    int sumVisitCount = Integer.parseInt(apiVisitCountListMap.get(i).get("visitCount").toString())  + Integer.parseInt(countList.get(j).get("visitCount").toString());  
	                    countList.get(j).put("visitCount", sumVisitCount);  
	                    flag = 1;  
	                    continue;  
	                }  
	            }  
	           if (flag == 0) {  
	                countList.add(apiVisitCountListMap.get(i));  
	           }  
    	   }
    	   
    	   Collections.sort(countList, new Comparator<Map<String,Object>>(){
				@Override
				public int compare(Map<String, Object> o1, Map<String, Object> o2) {
					int temp=Integer.valueOf(o1.get("visitCount").toString())>Integer.valueOf(o2.get("visitCount").toString())?-1:0;
					return temp;
				}
   			
   		});
     		browserArray.add(browserObject);
     		resultMap.put("browser", browserArray);
     		resultMap.put("apiVisit", countList);
     		resultMap.put("list", apiAbilityStatisticsList);
     	}
		return resultMap;
	}
*/
	@Override
	public List<Map<String, Object>> selectApplicationInvocationApiCount(String type) {
		SimpleDateFormat sdfToday=new SimpleDateFormat("yyyy-MM-dd"); 
		SimpleDateFormat sdfMonth=new SimpleDateFormat("yyyy-MM"); 
		SimpleDateFormat sdfYear=new SimpleDateFormat("yyyy");
		List<Map<String, Object>> applicationInvocationApiCount=null;
		if("1".equals(type)) {
			applicationInvocationApiCount=apiAbilityStatisticsMapper.selectApplicationInvocationApiCountDay(sdfToday.format(new Date()));
			
		}
		if("2".equals(type)) {
			applicationInvocationApiCount=apiAbilityStatisticsMapper.selectApplicationInvocationApiCountMonth(sdfMonth.format(new Date()));
			
		}
		if("3".equals(type)) {
			applicationInvocationApiCount=apiAbilityStatisticsMapper.selectApplicationInvocationApiCountYear(sdfYear.format(new Date()));
			
		}
		if(applicationInvocationApiCount!=null &&applicationInvocationApiCount.size()>0) {
			for (Map<String, Object> map : applicationInvocationApiCount) {
				Apply apply = applyManageMapper.selectApplyByAppKey(map.get("appKey").toString());
				if(apply==null) {
					continue;
				}else {
					map.put("name", apply.getApplyName());
					
				}
				
			}
			
			
		}
		return applicationInvocationApiCount;
	}

	//@Override
	/*public List<Map<String, Object>> selectApiInvocationCountTop5(String type) {
		SimpleDateFormat sdfToday=new SimpleDateFormat("yyyy-MM-dd"); 
		SimpleDateFormat sdfMonth=new SimpleDateFormat("yyyy-MM"); 
		SimpleDateFormat sdfYear=new SimpleDateFormat("yyyy");
		List<Map<String, Object>> apiInvocationCount=null;
		if("1".equals(type)) {
			apiInvocationCount=apiAbilityStatisticsMapper.selectApiInvocationCountTop5Day(sdfToday.format(new Date()));
			
		}
		if("2".equals(type)) {
			apiInvocationCount=apiAbilityStatisticsMapper.selectApiInvocationCountTop5Month(sdfMonth.format(new Date()));
			
		}
		if("3".equals(type)) {
			apiInvocationCount=apiAbilityStatisticsMapper.selectApiInvocationCountTop5Year(sdfYear.format(new Date()));
			
		}
		if(apiInvocationCount!=null&&apiInvocationCount.size()>0) {
			for (Map<String, Object> map : apiInvocationCount) {
				Apply apply = applyManageMapper.selectApplyByAppKey(map.get("appKey").toString());
				if(apply!=null) {
					DataMart dataMart = dataMartMapper.selectDataMart(apply.getCategoryId());
					map.put("typeName", dataMart.getMartName());
					if(LevelEnum.LEVELONE.getStatus().equals(apply.getLevel())) {
						map.put("applyLevel", LevelEnum.LEVELONE.getLabel());
					}
					if(LevelEnum.LEVELTWO.getStatus().equals(apply.getLevel())) {
						map.put("applyLevel", LevelEnum.LEVELTWO.getLabel());
					}
					if(LevelEnum.LEVELTHREE.getStatus().equals(apply.getLevel())) {
						map.put("applyLevel", LevelEnum.LEVELTHREE.getLabel());
					}
					map.put("apiCount", applyManageMapper.selectApiCountByApplyId(apply.getId()));
					
				}
				map.put("applyName", apply.getApplyName());
			}
			
		}
		return apiInvocationCount;
	}*/

	@Override
	public Map<String, Object> selectApiAbilityStatisticsList(String appKey) {
	    //1:响应平均时间,2:流量Qps,3:接口响应错误次数，4：带宽占用，5：各浏览器访问量,6:接口访问量
		SimpleDateFormat sdfToday=new SimpleDateFormat("yyyy-MM-dd"); 
		Map<String,Object> paramMap=new HashMap<String,Object>();
		Map<String,Object> resultMap=new HashMap<String,Object>();
		//平均响应时间
		paramMap.put("type", "1");
		paramMap.put("appKey", appKey);
		paramMap.put("date", sdfToday.format(new Date()));
		List<Map<String, Object>> responseTimeList = apiAbilityStatisticsMapper.selectApiAbilityStatisticsListByAppKeyAndType(paramMap);
		List<Map<String, Object>> avgResponseTime = doAvgResponseTime(responseTimeList);
		//平均带宽
		paramMap.put("type", "4");
		List<Map<String, Object>> responsrBandWidthlist = apiAbilityStatisticsMapper.selectApiAbilityStatisticsListByAppKeyAndType(paramMap);
		List<Map<String, Object>> avgBroadBand = doAvgBroadBand(responsrBandWidthlist);
		//2:流量Qps
		paramMap.put("type", "2");
		List<Map<String, Object>> qpsList = apiAbilityStatisticsMapper.selectApiAbilityStatisticsListByAppKeyAndType(paramMap);
		List<Map<String, Object>> qpsValue = doAvgValue(qpsList);
		//3:接口响应错误次数
		paramMap.put("type", "3");
		List<Map<String, Object>> errorList = apiAbilityStatisticsMapper.selectApiAbilityStatisticsListByAppKeyAndType(paramMap);
		List<Map<String, Object>> apiErrorCount = doApiErrorCount(errorList);
		//5：各浏览器访问量
		paramMap.put("type", "5");
		List<Map<String, Object>> browserCountList = apiAbilityStatisticsMapper.selectBrowserCountListByAppKeyAndType(paramMap);
		if(browserCountList!=null&&browserCountList.size()>0) {
			double sum=0;
			for(int i=0;i<browserCountList.size();i++) {
				if(browserCountList.get(i).get("browser_type").toString().indexOf("Mozilla")!=-1) {
					browserCountList.get(i).put("name","Firefox");
					browserCountList.get(i).put("value", 	browserCountList.get(i).get("countValue"));
				}else if(browserCountList.get(i).get("browser_type").toString().indexOf("Edge")!=-1) {
					browserCountList.get(i).put("name","Edge");
					browserCountList.get(i).put("value", 	browserCountList.get(i).get("countValue"));
 					
 				}else if(browserCountList.get(i).get("browser_type").toString().indexOf("OPR")!=-1) {
 					browserCountList.get(i).put("name","OPR");
 					browserCountList.get(i).put("value", 	browserCountList.get(i).get("countValue"));
 					
 				}else if(browserCountList.get(i).get("browser_type").toString().indexOf("Chrome")!=-1) {
 					browserCountList.get(i).put("name","Chrome");
 					browserCountList.get(i).put("value", 	browserCountList.get(i).get("countValue"));
 					
 				}else if(browserCountList.get(i).get("browser_type").toString().indexOf("Safari")!=-1) {
 					browserCountList.get(i).put("name","Safari");
 					browserCountList.get(i).put("value", 	browserCountList.get(i).get("countValue"));
 				}else {
 					browserCountList.get(i).put("name","Other");
 					sum+=Double.parseDouble(browserCountList.get(i).get("countValue").toString());
 					browserCountList.get(i).put("value", sum);
 				}
				
			}
			
		}
		//6:接口访问量
		paramMap.put("type", "6");
		List<Map<String, Object>> apiCountList = apiAbilityStatisticsMapper.selectApiCountListByAppKeyAndType(paramMap);
		if(apiCountList!=null &&apiCountList.size()>0) {
			for(int i=0;i<apiCountList.size();i++) {
				String apiUrl = apiCountList.get(i).get("app_key").toString();
				ApiManage apiManage = apiManageMapper.selectApiManageByUrl(apiUrl);
				if(apiManage==null) {
					continue;
				}
				apiCountList.get(i).put("name", apiManage.getName());
			}
			
		}
		resultMap.put("avgResponseTime", avgResponseTime);
		resultMap.put("avgBroadBand", avgBroadBand);
		resultMap.put("qpsValue", qpsValue);
		resultMap.put("apiErrorCount", apiErrorCount);
		resultMap.put("browserCount", browserCountList);
		resultMap.put("apiCountTop5", apiCountList);
		return resultMap;
	}
	private List<Map<String, Object>> doAvgResponseTime(List<Map<String, Object>> responseTimeList){
		List<Map<String,Object>> resList=new ArrayList<Map<String,Object>>();
		if(responseTimeList!=null && responseTimeList.size()>0) {
			for(int i=0;i<responseTimeList.size();i++) {
				Map<String,Object> temp=new HashMap<String,Object>();
				if(responseTimeList.size()==1) {
					temp.put("time", responseTimeList.get(i).get("time"));
					double countValue = Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
					double apiVisist = Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
					temp.put("avgValue", String.format("%.8f", countValue/apiVisist));
					resList.add(temp);
				}
				if(i+1==responseTimeList.size()) {
					break;
				}
				double countValueDiff= Double.parseDouble(responseTimeList.get(i+1).get("countValue").toString())-Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
				double apiVisistDiff=Double.parseDouble(responseTimeList.get(i+1).get("apiVisist").toString())-Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
				if(apiVisistDiff==0) {
					apiVisistDiff=1;
				}
				double avgResponseTime=countValueDiff/apiVisistDiff;
				temp.put("time", responseTimeList.get(i+1).get("time"));
				temp.put("avgValue", String.format("%.8f",avgResponseTime));
				resList.add(temp);
			}
		}
		return resList;
	}
	private List<Map<String, Object>> doAvgValue(List<Map<String, Object>> responseTimeList){
		List<Map<String,Object>> resList=new ArrayList<Map<String,Object>>();
		if(responseTimeList!=null && responseTimeList.size()>0) {
			for(int i=0;i<responseTimeList.size();i++) {
				Map<String,Object> temp=new HashMap<String,Object>();
				if(responseTimeList.size()==1) {
					temp.put("time", responseTimeList.get(i).get("time"));
					//double countValue = Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
					double apiVisist = Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
					temp.put("avgValue", String.format("%.2f", apiVisist));
					resList.add(temp);
				}
				if(i+1==responseTimeList.size()) {
					break;
				}
				//double countValueDiff= Double.parseDouble(responseTimeList.get(i+1).get("countValue").toString())-Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
				double apiVisistDiff=Double.parseDouble(responseTimeList.get(i+1).get("apiVisist").toString())-Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
				//double avgResponseTime=countValueDiff/apiVisistDiff;
				temp.put("time", responseTimeList.get(i+1).get("time"));
				temp.put("avgValue", String.format("%.2f",apiVisistDiff));
				resList.add(temp);
			}
		}
		return resList;
	}
	private List<Map<String, Object>> doApiErrorCount(List<Map<String, Object>> responseTimeList){
		List<Map<String,Object>> resList=new ArrayList<Map<String,Object>>();
		if(responseTimeList!=null && responseTimeList.size()>0) {
			for(int i=0;i<responseTimeList.size();i++) {
				Map<String,Object> temp=new HashMap<String,Object>();
				if(responseTimeList.size()==1) {
					temp.put("time", responseTimeList.get(i).get("time"));
					double countValue = Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
					//double apiVisist = Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
					temp.put("avgValue", String.format("%.2f", countValue));
					resList.add(temp);
				}
				if(i+1==responseTimeList.size()) {
					break;
				}
				double countValueDiff= Double.parseDouble(responseTimeList.get(i+1).get("countValue").toString())-Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
				//double apiVisistDiff=Double.parseDouble(responseTimeList.get(i+1).get("apiVisist").toString())-Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
				//double avgResponseTime=countValueDiff/apiVisistDiff;
				temp.put("time", responseTimeList.get(i+1).get("time"));
				temp.put("avgValue", String.format("%.2f",countValueDiff));
				resList.add(temp);
			}
		}
		return resList;
	}
	private List<Map<String, Object>> doAvgBroadBand(List<Map<String, Object>> responseTimeList){
		List<Map<String,Object>> resList=new ArrayList<Map<String,Object>>();
		if(responseTimeList!=null && responseTimeList.size()>0) {
			for(int i=0;i<responseTimeList.size();i++) {
				Map<String,Object> temp=new HashMap<String,Object>();
				if(responseTimeList.size()==1) {
					temp.put("time", responseTimeList.get(i).get("time"));
					double countValue = Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
					double apiVisist = Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
					temp.put("avgValue", String.format("%.2f", countValue/apiVisist/1024));
					resList.add(temp);
				}
				if(i+1==responseTimeList.size()) {
					break;
				}
				double countValueDiff= Double.parseDouble(responseTimeList.get(i+1).get("countValue").toString())-Double.parseDouble(responseTimeList.get(i).get("countValue").toString());
				double apiVisistDiff=Double.parseDouble(responseTimeList.get(i+1).get("apiVisist").toString())-Double.parseDouble(responseTimeList.get(i).get("apiVisist").toString());
				if(apiVisistDiff==0) {
					apiVisistDiff=1;
				}
				double avgResponseTime=countValueDiff/apiVisistDiff;
				temp.put("time", responseTimeList.get(i+1).get("time"));
				temp.put("avgValue", String.format("%.2f",avgResponseTime/1024));
				resList.add(temp);
			}
		}
		return resList;
	}

	@Override
	public List<Map<String, Object>> selectApiInvocationCountTop5() {
		List<Map<String, Object>> apiInvocationCount = apiAbilityStatisticsMapper.selectApiInvocationCountTop5Day();
		if(apiInvocationCount!=null&&apiInvocationCount.size()>0) {
			for (Map<String, Object> map : apiInvocationCount) {
				Apply apply = applyManageMapper.selectApplyByAppKey(map.get("appKey").toString());
				if(apply!=null) {
					DataMart dataMart = dataMartMapper.selectDataMart(apply.getCategoryId());
					map.put("typeName", dataMart.getMartName());
					if(LevelEnum.LEVELONE.getStatus().equals(apply.getLevel())) {
						map.put("applyLevel", LevelEnum.LEVELONE.getLabel());
					}
					if(LevelEnum.LEVELTWO.getStatus().equals(apply.getLevel())) {
						map.put("applyLevel", LevelEnum.LEVELTWO.getLabel());
					}
					if(LevelEnum.LEVELTHREE.getStatus().equals(apply.getLevel())) {
						map.put("applyLevel", LevelEnum.LEVELTHREE.getLabel());
					}
					map.put("apiCount", applyManageMapper.selectApiCountByApplyId(apply.getId()));
					
				}
				map.put("applyName", apply.getApplyName());
			}
		}
		return apiInvocationCount;
	}
	
}
